package org.chartsy.spearman;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.text.DecimalFormat;
import java.util.LinkedHashMap;
import org.chartsy.main.ChartFrame;
import org.chartsy.main.chart.Indicator;
import org.chartsy.main.data.DataItem;
import org.chartsy.main.data.Dataset;
import org.chartsy.main.utils.DefaultPainter;
import org.chartsy.main.utils.Range;
import org.chartsy.main.utils.SerialVersion;
import org.openide.nodes.AbstractNode;
/**
*
* @author Viorel
*/
public class Spearman extends Indicator
{
private static final long serialVersionUID = SerialVersion.APPVERSION;
public static final String SPEARMAN = "spearman";
public static final String SMA = "sma";
private IndicatorProperties properties;
public Spearman()
{
super();
properties = new IndicatorProperties();
}
public @Override String getName()
{
return "Spearman Indicator";
}
public @Override String getLabel()
{
StringBuilder builder = new StringBuilder();
builder.append(properties.getLabel());
builder.append(" (").append(properties.getPeriod()).append(")");
return builder.toString();
}
public @Override String getPaintedLabel(ChartFrame cf)
{
return getLabel();
}
public @Override Indicator newInstance()
{
Indicator indicator = new Spearman();
return indicator;
}
public @Override LinkedHashMap getHTML(ChartFrame cf, int i)
{
LinkedHashMap ht = new LinkedHashMap();
DecimalFormat df = new DecimalFormat("#,##0.00");
double[] values = getValues(cf, i);
String[] labels = {"Spearman:", "SMA:"};
ht.put(getLabel(), " ");
if (values.length > 0) {
Color[] colors = getColors();
for (int j = 0; j < values.length; j++)
{
ht.put(getFontHTML(colors[j], labels[j]),
getFontHTML(colors[j], df.format(values[j])));
}
}
return ht;
}
public @Override void paint(Graphics2D graphics, ChartFrame chartFrame, Rectangle bounds)
{
Dataset spearman = visibleDataset(chartFrame, SPEARMAN);
Dataset sma = visibleDataset(chartFrame, SMA);
if (spearman != null)
{
if (maximized)
{
Range range = getRange(chartFrame);
DefaultPainter.line(
graphics, chartFrame, range, bounds, spearman,
properties.getColor(), properties.getStroke()); // paint line
if (sma != null)
{
DefaultPainter.line(
graphics, chartFrame, range, bounds, sma,
properties.getSMAColor(), properties.getSMAStroke()); // paint sma line
}
}
}
}
public @Override void calculate()
{
long[] times = getDataset().getTimeValues();
double[] closes = getDataset().getCloseValues();
int count = getDataset().getItemsCount();
int period = properties.getPeriod();
Dataset spearman = Dataset.EMPTY(count);
for (int i = period; i < count; i++)
{
double[] r1 = new double[period], // time series order
r2 = new double[period],
r11 = new double[period], // price (close)
r21 = new double[period], // internal sort table
r22 = new double[period]; // order of prices (close)
for (int j = 0; j < period; j++)
{
r1[j] = j;
r22[j] = j;
r11[j] = closes[i - period + j];
r21[j] = closes[i - period + j];
}
int changed = 1;
while (changed > 0)
{
changed = 0;
for (int j = 0; j < period - 1; j++)
{
if (r21[j + 1] < r21[j])
{
double temp = r21[j];
r21[j] = r21[j + 1];
r21[j + 1] = temp;
changed = 1;
}
}
}
for (int j = 0; j < period; j++)
{
int found = 0;
while (found < 1)
{
for (int k = 0; k < period; k++)
{
if (r21[k] == r11[j])
{
r22[j] = k;
found = 1;
}
}
}
}
double absum = 0;
for (int j = 0; j < period; j++)
{
double ab = r1[j] - r22[j];
double ab2 = Math.pow(ab, 2);
absum += ab2;
}
double coefcorr = (1 - (6 * absum) / (period * (period * period - 1)));
long time = times[i];
double close = 100 * coefcorr;
DataItem item = new DataItem(time, close);
spearman.setDataItem(i, item);
}
int smaPeriod = properties.getSMAPeriod();
Dataset sma = Dataset.SMA(spearman, smaPeriod);
addDataset(SPEARMAN, spearman);
addDataset(SMA, sma);
}
public @Override boolean hasZeroLine()
{
return false;
}
public @Override boolean getZeroLineVisibility()
{
return false;
}
public @Override Color getZeroLineColor()
{
return null;
}
public @Override Stroke getZeroLineStroke()
{
return null;
}
public @Override boolean hasDelimiters()
{
return false;
}
public @Override boolean getDelimitersVisibility()
{
return false;
}
public @Override double[] getDelimitersValues()
{
return new double[] {};
}
public @Override Color getDelimitersColor()
{
return null;
}
public @Override Stroke getDelimitersStroke()
{
return null;
}
public @Override Color[] getColors()
{
return new Color[]
{
properties.getColor(),
properties.getSMAColor()
};
}
public @Override double[] getValues(ChartFrame chartFrame)
{
if (datasetExists(SPEARMAN) && datasetExists(SMA))
return new double[]
{
visibleDataset(chartFrame, SPEARMAN).getLastClose(),
visibleDataset(chartFrame, SMA).getLastClose()
};
return new double[] {};
}
public @Override double[] getValues(ChartFrame chartFrame, int i)
{
if (datasetExists(SPEARMAN) && datasetExists(SMA))
return new double[]
{
visibleDataset(chartFrame, SPEARMAN).getCloseAt(i),
visibleDataset(chartFrame, SMA).getCloseAt(i)
};
return new double[] {};
}
public @Override boolean getMarkerVisibility()
{
return properties.getMarker();
}
public @Override AbstractNode getNode()
{
return new IndicatorNode(properties);
}
@Override
public Range getRange(ChartFrame cf)
{
if (datasets.isEmpty())
return new Range();
Dataset spearman = visibleDataset(cf, SPEARMAN);
Dataset sma = visibleDataset(cf, SMA);
double min = Math.min(
spearman.getMin(Dataset.CLOSE_PRICE),
sma.getMin(Dataset.CLOSE_PRICE));
double max = Math.max(
spearman.getMax(Dataset.CLOSE_PRICE),
sma.getMax(Dataset.CLOSE_PRICE));
max = Math.max(max, Math.abs(min));
max = Math.round(max);
max = max + (10 - (max % 10)) + 10;
min = -1 * max;
Range range = new Range(min, max);
return range;
}
@Override
public Double[] getPriceValues(ChartFrame cf)
{
Double[] values = new Double[5];
Range range = getRange(cf);
double max = range.getUpperBound() - 10;
values[0] = new Double(0);
values[1] = new Double(max);
values[2] = new Double(max / 2);
values[3] = new Double(-1 * max);
values[4] = new Double((-1 * max) / 2);
return values;
}
}